import java.util.List;
import java.util.concurrent.TimeUnit;

import org.omg.CORBA.BooleanHolder;
import org.omg.CORBA.StringHolder;

import common.CommonTools;
import common.Player;
import administrator.administratorServicePOA;


public class AdministratorServiceImpl extends administratorServicePOA {

	private String geolocation;

	protected AdministratorServiceImpl(String geolocation) {
		super();
		this.geolocation = geolocation;
	}
	
	@Override
	public void getPlayerStatus(String adminUsername, String adminPassword,String iPAddress, BooleanHolder result, StringHolder playersStatus) {
		
		String responseFromEU = null;
		String responseFromAS = null;
		String responseFromNA = null;

		CommonTools.writeLog("server", geolocation,	"New admin call for getPlayerStatus at " + geolocation
							+ " server", "server");

		if ((!adminUsername.equals("Admin"))
				|| (!adminPassword.equals("Admin"))) {
			CommonTools.writeLog("server", geolocation,
					"Wrong admin credentiels at " + geolocation + " server",
					"server");
			
			playersStatus.value = "Wrong admin credentiels at "	+ geolocation + " server";
			result.value  = false;
			return;
			
		}
		
		
		String groupID = String.valueOf(geolocation.charAt(2));
		CommonTools.writeLog("server", geolocation,	"server:"
				+ geolocation + " groupID:"+groupID, "server");
		
		if (geolocation.startsWith("EU")) {
			responseFromEU = UDPTools.getLocalUserStatus();

			responseFromNA = getUDPResult("NA"+groupID, "EU"+groupID);
			responseFromAS = getUDPResult("AS"+groupID, "EU"+groupID);

		} else if (geolocation.startsWith("AS")) {
			responseFromAS = UDPTools.getLocalUserStatus();
			responseFromNA = getUDPResult("NA"+groupID, "AS"+groupID);
			responseFromEU = getUDPResult("EU"+groupID, "AS"+groupID);

		} else if (geolocation.startsWith("NA")) {
			responseFromNA = UDPTools.getLocalUserStatus();
			responseFromEU = getUDPResult("EU"+groupID, "NA"+groupID);
			responseFromAS = getUDPResult("AS"+groupID, "NA"+groupID);
		}

		responseFromNA = (responseFromNA == null) ? "" : responseFromNA.trim();
		responseFromEU = (responseFromEU == null) ? "" : responseFromEU.trim();
		responseFromAS = (responseFromAS == null) ? "" : responseFromAS.trim();

		String response = "NA" + ":"+ responseFromNA + " EU" +":" + responseFromEU
				+ " AS" + ":" + responseFromAS;

		CommonTools.writeLog("server", geolocation,	"Response sent for  admin call for getPlayerStatus from "
						+ geolocation + " server Result:groupID:"+groupID +":" + response, "server");

		playersStatus.value = response;
		result.value  = true;
		return;
	}

	private String getUDPResult(String geolocation, String geolocationCaller) {
		
		UDPClient uDPClient = new UDPClient(CommonTools.getproperty(
				"server.properties", "serverName_" + geolocation),
				Integer.parseInt(CommonTools.getproperty("server.properties",
						"UDPPort_" + geolocation)), geolocation,
				geolocationCaller);

		Thread thread = new Thread(uDPClient);
		thread.start();
		int timeCounter = 0;

		while ((thread.isAlive()) && (timeCounter < 20)) {
			try {
				TimeUnit.MILLISECONDS.sleep(200);
				timeCounter++;
				CommonTools.writeLog("server", geolocation,
						"we are waiting for UDP response 2: " + geolocation
								+ " server", "server");

			} catch (InterruptedException e) {
				CommonTools.writeLog("server", geolocation,
						"Exception while waiting for UDP response at : "
								+ geolocation + " server", "server");

			}
		}

		return uDPClient.getResult();


	}

	@Override
	public void suspendAccount(String adminUsername, String adminPassword,String iPAddress, String UsernameToSuspend, BooleanHolder result, StringHolder status) {
		
		Player playerNew = new Player(" ", " ", 0, UsernameToSuspend, " ", "");
		
		if (!CommonTools.isLegalIpAddress(iPAddress, geolocation)) {
			CommonTools.writeLog("server", geolocation,
					"Wrong IP Address:" + playerNew, "server");		
			status.value = "server" + geolocation + " Wrong IP Address:" + playerNew;
			result.value  = false;
			return;
		}
		if ((!adminUsername.equals("Admin"))
				|| (!adminPassword.equals("Admin"))) {
			CommonTools.writeLog("server", geolocation,
					"Wrong admin credentiels at " + geolocation + " server",
					"server");
			
			status.value = "Wrong admin credentiels at "	+ geolocation + " server";
			result.value  = false;
			return;
			
		}
		boolean userExist = false;
		List<Player> list = getList(UsernameToSuspend);
		if (list == null) {
			CommonTools.writeLog("server", geolocation,
					"User Does not exit:empty list " + playerNew, "server");
			CommonTools.writeLog(UsernameToSuspend, geolocation,
					"User Does not exit: " + playerNew, "server");
			status.value = "server" + geolocation + " User Does not exit: empty list" + playerNew;
			result.value  = false;
			return;
		}
		//System.out.println("before synchro");
		synchronized (list) {
			for (int i = 0; i < list.size(); i++) {
				Player p = list.get(i);
				if (p.getUserName().equals(UsernameToSuspend)
						&& p.getIPAddress().equals(iPAddress)) {
					userExist = true;
					list.remove(i);
					
					CommonTools.writeLog("server", geolocation,
							" account suspended: " + playerNew, "server");
					CommonTools.writeLog(UsernameToSuspend, geolocation,
							" account suspended: " + playerNew, "server");
					status.value ="server" + geolocation + "  account suspended: " + playerNew;				
					result.value  = true;
					return;
				}
			}
		}
		if (!userExist) {
			
			CommonTools.writeLog("server", geolocation,
					"User Does not exit: " + playerNew, "server");
			CommonTools.writeLog(UsernameToSuspend, geolocation,
					"User Does not exit: " + playerNew, "server");
			status.value = "server" + geolocation + " User Does not exit:  " + playerNew;
			result.value  = false;
			return;

		}

	}
	
	@Override
	public void haltLocalServer(BooleanHolder result, StringHolder status) {
		new Thread(new haltTask()).start();
		result.value = true;
		return;
	}
	public  void halt(){
		//LocalServer.playerServiceImpl = null;
		//LocalServer.administratorServiceImpl = null;
		
		CommonTools.writeLog(
				"server",
				"EU",
				"Administrator UDP service started at: "
						+ "EU"
						+ " server on the port: "
						+ CommonTools.getproperty("server.properties",
								"UDPPort_" + "EU"), "server");
	}
	class haltTask implements Runnable{
		@Override
		public void run() {
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			//LocalServer localServer = new LocalServer(geolocation);
			halt();
		}
		
	}
	
	
	private List getList(String userName) {
		String key = userName.substring(0, 1).toUpperCase();
		
		PlayerHashTable hashTable = PlayerHashTable.getInstance();
		
		List<Player> list = (List<Player>) hashTable.get(key);
		return list;
	}

}
